package libra;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpStatus;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;

import libra.forSentinel.BlockExHandler_RestTemplate;

/**
 * SpringBoot启动入口 
 * @author libra
 */
//标注该类为SpringBoot的主配置类
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})// 排除前端门户的数据库自动装配
//指定包扫描
@ComponentScan(value={"libra"})
// 扫描Servlet组件
@ServletComponentScan(value="libra")
/*
 * @EnableEurekaClient 与 @EnableDiscoveryClient
 * 在功能上是一致的：写在启动类的上，开启服务注册发现功能。
 * @EnableEurekaClient只适用于Eureka作为注册中心，@EnableDiscoveryClient 可以是其他注册中心。
 */
// 开启EurekaClient的注解，连接EurekaServer
//@EnableEurekaClient
@EnableDiscoveryClient
public class MainStart_Sentinel_Consumer_Rest_30800 {
	public static void main(String[] args) {
		System.out.println("MainStart.main()");
		ConfigurableApplicationContext cac = SpringApplication.run(MainStart_Sentinel_Consumer_Rest_30800.class, args);
	}
	
	@Bean
	@LoadBalanced
	@SentinelRestTemplate(
	    blockHandler = "handleException", blockHandlerClass = BlockExHandler_RestTemplate.class,
	    fallback = "handleFallback",fallbackClass = BlockExHandler_RestTemplate.class
	)
	public RestTemplate restTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
		list.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
		list.add(new ByteArrayHttpMessageConverter());
		list.add(new AllEncompassingFormHttpMessageConverter());
		list.add(new MappingJackson2HttpMessageConverter());
		restTemplate.setMessageConverters(list);
		// 设置RestTemplate的请求异常处理，该设置可以处理Provider端的流控异常
//		restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
//			@Override
//			public boolean hasError(ClientHttpResponse response) throws IOException {
//		        return super.hasError(response);
//			}
//			@Override
//			public void handleError(ClientHttpResponse response) throws IOException {
//				int rawStatusCode = response.getRawStatusCode();
//				if( rawStatusCode == 429 ) {
//					byte[] b = new byte[response.getBody().available()];
//					response.getBody().read(b);
//					System.err.println( "restTemplate.ErrorHandler():" + new String(b) );
//		            throw new HttpClientErrorException(response.getStatusCode(), response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
//				} else {
//					super.handleError(response);
//				}
//			}
//		});
		return restTemplate;
	}
}
